#include "log_txt.hpp"

#include <string.h>
#include <stdio.h>
#include <iostream>

#ifdef _WIN32
#define snprintf _snprintf
#endif


static const char* LogLevelStr[] = {"INFO", "WARNING", "ERROR", "CRITICAL"};

namespace lge2d
{
namespace core
{

ILog* CreateLog()
{
	return (new LogTxt());
}

void DestroyLog(ILog* log)
{
	delete log;
}
//////////////////////////////////////////////////////////////////////////
LogTxt::LogTxt(unsigned bufferSize/* = 2048*/) :
	m_bufferSize(bufferSize),
	m_level(InfoLevel)
{
	m_clock.Reset();
	m_buff = new char[m_bufferSize];
}


LogTxt::~LogTxt()
{
	if (m_buff)
	{
		delete [] m_buff;
		m_buff = 0;
	}
}

void LogTxt::SetLogLevel(ILog::LogLevel level)
{
	if(level > CriticalLevel)
		level = CriticalLevel;

	m_level = level;
}

ILog::LogLevel LogTxt::GetLogLevel() const
{
	return m_level;
}

void LogTxt::Log( LogLevel level, const char* msg, ... )
{
	va_list vl;
	va_start(vl, msg);
	LogArgv(level, msg, vl);
	va_end(vl);
}

void LogTxt::Info(const char* msg, ... )
{
	va_list vl;
	va_start(vl, msg);
	LogArgv(InfoLevel, msg, vl);
	va_end(vl);
}

void LogTxt::Warning(const char* msg, ... )
{
	va_list vl;
	va_start(vl, msg);
	LogTxt::LogArgv(WarningLevel, msg, vl);
	va_end(vl);
}

void LogTxt::Error(const char* msg, ... )
{
	va_list vl;
	va_start(vl, msg);
	LogArgv(ErrorLevel, msg, vl);
	va_end(vl);
}

void LogTxt::Critical(const char* msg, ... )
{
	va_list vl;
	va_start(vl, msg);
	LogArgv(CriticalLevel, msg, vl);
	va_end(vl);
}

void LogTxt::LogArgv(LogLevel level, const char* msg, va_list args)
{
	// TODO: сделать через буферы для потоков,
	// так как такой вариант приводит к постоянным блокировкам
	//m_mutex.Lock();
	//
	if(level > CriticalLevel)
		level = CriticalLevel;
	
	if (level < m_level)
		return;

	const float elapsedTime = m_clock.GetElapsedTime();
	snprintf( m_buff, m_bufferSize, "%s (%.4f): ", LogLevelStr[level], elapsedTime);
	int len = strlen(m_buff);
	char* ptr = m_buff + len;
	vsnprintf(ptr, m_bufferSize - len, msg, args);
	strcat(m_buff, "\n");

	// output
	std::cout<<m_buff;
	//
	//m_mutex.Unlock();
}

} /* namespace core */
} /* namespace lge2d */

